﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////

// Reviewed

#pragma once

#include "GcmpModelInterface.h"
#include "NdbDataSchema.h"
#include "IElement.h"
#include "ElementCreationOptions.h"
#include "CollaborationScope.h"

namespace gcmp
{

    class IGraphicsMaterialData;

    /// \brief 图形材质
    ///
    /// 图形材质，通过此类可以创建图形材质
    class GCMP_MODEL_INTERFACE_EXPORT IGraphicsMaterial : public gcmp::IElement
    {
        DECLARE_CLASS_WITHOUT_DATA_MEMBERS(gcmp, IGraphicsMaterial, gcmp::IElement, 9530A2A4 - CB9A - 43EB - A912 - 13E8CF78E6B0, gcmpmodelinterface)

    public:

#pragma region static methods
        /// \brief 创建图形材质
        ///
        /// 创建不针对目标类别的图形材质，同时创建一个材质实例与其绑定且不能解绑。
        /// 材质实例初始值使用 IGraphicsMaterialData::Reset() 的默认实参进行初始化
        /// \param pDocument 图形材质所属的文档
        /// \param eco 图形材质的元素创建选项
        /// \param materialInstanceName 新创建的材质实例名
        /// \return 所创建的图形材质指针
        static IGraphicsMaterial* Create(IDocument* pDocument, ElementCreationOptions eco, const std::wstring& materialInstanceName);
      
        /// \brief 创建协同图形材质
        ///
        /// 协同环境下使用，非协同环境创建失败返回空。
        /// 需要调用者指出正在创建的是项目级还是专业级对象。
        /// 使用IGraphicsMaterial::Create(IDocument*, ElementCreationOptions, const std::wstring&)，等效于创建工作单元私有对象。
        ///
        /// \param pDocument 图形材质所在文档
        /// \param eco 图形材质的元素创建选项
        /// \param collaborationContext 协同基本信息，包括项目Id、影响范围(是项目级还是专业级)、专业(在scope为专业级时有效)
        /// \param [out] pErrorMessage错误信息。传入不为空，如果出错，传出错误信息；为空不传出。
        /// \return 新创建的图形材质
        static IGraphicsMaterial* Create(IDocument* pDocument, ElementCreationOptions eco,
            CollaborationContext& collaborationContext, const UniIdentity& categoryUid, std::wstring* pErrorMessage);

        /// \brief 获取文档中所有的图形材质
        ///
        /// \param pDoc 图形材质所在文档
        /// \return 文档中所有的图形材质，不包括来自嵌套族的材质
        static std::vector<IGraphicsMaterial*> GetAllGraphicsMaterials(IDocument* pDoc);
#pragma endregion static methods

    public:
        /// \brief 获取图形材质目标类别的 Uid
        /// 
        /// 目标类别是指该类别使用当前图形材质的数据进行渲染
        /// 若图形材质不针对任何目标类别，就返回 UniIdentity::InvalidUid
        /// 针对目标类别的图形材质可以不绑定材质实例，不针对目标类别的图形材质必定和某个材质实例绑定
        /// 针对目标类别的图形材质由系统创建，用户只能创建不针对目标类别的图形材质
        /// \return 图形材质目标类别的 Uid
        virtual UniIdentity GetTargetCategoryUid() const = 0;

        /// \brief 是否和材质实例绑定
        /// 
        /// 针对目标类别的图形材质可以不绑定材质实例，不针对目标类别的图形材质必定和某个材质实例绑定
        /// \return true-绑定，false-不绑定
        virtual bool IsBoundWithMaterialInstance() const = 0;

        /// \brief 绑定材质实例
        /// 
        /// 绑定材质实例的操作只能用于针对目标类别的图形材质，且必须先解除已有的绑定
        /// 对于不针对目标类别的图形材质此函数不适用（因为材质实例无法解绑）
        /// \param graphicsMaterialId 绑定用的材质实例来自于此图形材质
        /// \return true-绑定成功，false-绑定失败
        virtual bool BindMaterialInstance(const ElementId& graphicsMaterialId) = 0;

        /// \brief 与材质实例解绑
        /// 
        /// 针对目标类别的图形材质可以和材质实例解绑，不针对目标类别的图形材质不能和材质实例解绑
        /// \return true-解绑成功，false-解绑失败
        virtual bool UnbindMaterialInstance() = 0;
        
        /// \brief 更新材质实例
        /// 
        /// 为绑定的材质实例更新数据
        /// \param data 图形材质数据，更新用的数据来源
        /// \return true-更新成功，false-更新失败
        virtual bool UpdateMaterialInstanceByGraphicsMaterialData(const IGraphicsMaterialData& data) = 0;

        /// \brief 获取图形材质数据
        /// \return 图形材质数据，来自于材质实例
        virtual OwnerPtr<IGraphicsMaterialData> GetGraphicsMaterialDataFromMaterialInstance() const = 0;

        /// \brief 为绑定的材质实例改名
        /// \param newName 新名字
        /// \return true-改名成功，false-改名失败
        virtual bool RenameMaterialInstance(const std::wstring& newName) = 0;

        /// \brief 获取绑定的材质实例名
        /// \param name 返回材质实例的名字
        /// \return true-成功，false-失败
        virtual bool GetMaterialInstanceName(std::wstring& name) const = 0;
        
        /// \brief 从材质实例获取与 Falcon 对接用的数据
        /// \return 与 Falcon 对接用的数据，空表示失败
        virtual std::wstring GetDataForFalconFromMaterialInstance() const = 0;

        /// \brief 获取图形材质的拥有者
        /// \return 返回图形材质的拥有者
        virtual ElementId GetOwnerId() const = 0;

        /// \brief 设置图形材质的拥有者
        ///
        /// 设置图形材质的拥有者
        /// ，比如图形材质是从族导入的
        /// ，这个图形材质的拥有者就是这个族
        /// ，拥有者被删除时
        /// ，图形材质也会被删除
        /// \param idOwner 图形材质的拥有者ID
        /// \return 返回是否设置成功
        virtual bool SetOwnerId(const ElementId& idOwner) = 0;

    public:
        /// \brief 获取Implementation Uid
        ///
        /// \return UniIdentity 返回ImplementationUid
        static UniIdentity GetImplementationUid();

        /// \brief 获取图形材质协同影响范围
        ///
        /// \return 该图形材质协同影响范围
        virtual CollaborationScope GetCollaborationScope() const = 0;

        /// \brief 获取图形材质协同专业
        ///
        /// 为空表示该图形材质协同影响范围不为专业级别
        /// \return 该图形材质协同专业
        virtual std::wstring GetCollaborationSpecialty() const = 0;

        /// \brief 获取图形材质绑定的材质转成的Json字符串
        ///
        /// 为空表示该图形材质没有绑定材质实例
        /// \return Json字符串
        virtual std::wstring GetJsonStringFromMaterialInstance() const = 0;

        /// \brief 使用Json字符串更新图形材质绑定的材质实例
        ///
        /// 必须已经绑定一个材质实例
        /// \return 更新是否成功
        virtual bool UpdateMaterialInstanceByJsonString(const std::wstring& jsonStr) = 0;
    };
}


